一応以下のようにすれば非同期読み込みになります。
<script async src="..."></script>
ですが、これだと100%読み込む事になってしまうので、読み込みたいタイミングで読み込む方法です。
script を動的に作成する
流れは、
<script>
タグを作る属性を設定
<body>
あたりに埋め込む
です。
script タグを作る
document.createElement
を使います。script
を作りたいなら、
const script = document.createElement('script');
です。これで DOM 上にはまだありませんが、<script>
タグが作れました。
属性を設定
以下でasync
とsrc
辺りを設定します。
script.async = 1;
script.src = '...';
body あたりに埋め込む
<script>
は DOM に埋め込んでから初めてソースを読み込んでくれるので DOM に追加してあげます。
一番てっとり早いのが<body>
タグに埋め込む方法だと思います。これは<body>
タグがあればdocument.body
で取得できます。もし、ない場合は何かの要素にid
を振りdocument.getElementById
などを使うといいです。
ある要素の下に要素を追加するにはNode#appendChild
を使います。以下は追加するコードです。
document.body.appendChild(script);
これでこのような HTML になり読み込みしてくれるはずです。
<body>
<script async src="..."></script>
</body>
読み込みが終わったタイミングを知る
非同期で読み込むソースが何か別ソースの依存だったり、処理の関係上「Aの読み込みが確実に終わった後にBの処理をしたい」ということは結構あると思います。これには<script>
のload
イベントを使います。
load
イベントは<script>
はソースが読み込み終わった時に発火されます。そのハンドラー関数に続きの処理を書いた関数を設定すれば順番に処理を実行できますね。これは、DOM に追加する前に設定する必要があります。
script.addEventListener('load', () => {
alert('読み込み完了');
};
document.body.appendChild(script);
script 埋め込みを非同期関数化する
そのソースの読み込み自体を非同期関数にすると何かと便利に扱えます。これはnew Promise
を返しload
のハンドラー関数にそのresolve
を指定するだけです。
const loadScriptXxx = () => {
return new Promise(resolve => {
/** 上記の内容 */
script.addEventListener('load', resolve);
/** 上記の内容 */
});
};
これでasync-await
で分かりやすく書けるかもです。
(async () => {
await loadScriptXxx();
await loadScriptYyy(); // 例えば Xxx 依存
await loadScriptZzz(); // 例えば Yyy 依存
alert('Xxx, Yyy, Zzz 読み込み完了!')
})();